home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume91
/
news
/
barn_201
/
part01
/
article.c
next >
Wrap
C/C++ Source or Header
|
1991-02-07
|
9KB
|
316 lines
/*
* File Name: article.c
* Project: BARN - Bah's Amiga ReadNews.
* Purpose: Parse header fields in a news article.
* Functions: ParseArticle, GetNextHeader, DumpArticle, DestroyArticle.
* Author: Jeff Van Epps
* Created: 02 Sep 89
* Last Modified: 05 Jan 91
* Comments:
* History:
* 02 Sep 89/JVE Created.
* 28 Sep 89/JVE ParseArticle now stores position within file where
* headers end and text begins in article->textpos.
* 30 Dec 89/JVE Added "Sender:" to list of useful headers. This list
* will go away when there is a config file to do same.
* 18 Oct 90/JVE Use HDR_xxx defines instead of hardcoded strings.
* Added GetHeader.
* 21 Oct 90/JVE Don't end header search until blank line.
* 05 Jan 91/JVE New "subject" field in article_info initialized to
* a NULL pointer and set to point at the SUBJECT header
* fieldvalue after all headers have been read.
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "standard.h"
# include "article.h"
# include "configure.h"
# include "variables.h"
/****************************************************************************/
/* FUNCTION: ParseArticle */
/* */
/* PURPOSE: Parses headers from article & creates article/header structs*/
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* filename I Name of file containing article. */
/* */
/* RETURNS: */
/* (ARTICLE_INFO *) Pointer to newly allocated article structure. */
/* NULLP(ARTICLE_INFO) Indication of failure. */
/* */
/* COMMENTS: */
/* Assumes filename contains only digits and is same as article */
/* number. */
/* */
/* HISTORY: */
/* 1. 02 Sep 89 Created. */
/* 2. 28 Sep 89 Added textpos to say where headers end. */
/* */
/****************************************************************************/
ARTICLE_INFO *ParseArticle( filename )
char *filename;
{
FILE *fp;
long id; /* article number (aka filename) */
ARTICLE_INFO *article; /* ptr to article information */
HEADER_INFO **hdr; /* handle for header field allocation */
HEADER_INFO *h;
if ( ( fp = fopen( filename, "r" ) ) == NULLP( FILE ) )
{
perror( filename );
return NULLP( ARTICLE_INFO );
}
else if ( ( id = atol( filename ) ) <= 0 )
{
printf( "%s: Bad article number.\n", filename );
return NULLP( ARTICLE_INFO );
}
/*
* Initialize article info structure.
*/
article = (ARTICLE_INFO *) malloc( sizeof( ARTICLE_INFO ) );
article->number = id;
article->next = NULLP( ARTICLE_INFO );
article->headers = NULLP( HEADER_INFO );
article->beenread = FALSE;
article->textpos = 0L;
article->done = FALSE;
article->subject = NULLP( char );
/*
* Get all header fields.
*/
hdr = &article->headers;
while ( GetNextHeader( fp, &hdr ) )
article->textpos = ftell( fp );
fclose( fp );
for ( h = article -> headers; h != NULLP( HEADER_INFO ); h = h -> next )
if ( strcmp( h -> fieldname, HDR_SUBJECT ) == 0 )
{
article -> subject = h -> fieldvalue;
break;
}
return article;
}
/****************************************************************************/
/* FUNCTION: GetNextHeader */
/* */
/* PURPOSE: Parses the next header field out of an article. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* fp I FILE pointer to file containing article. */
/* hdr I/O Where to put pointer to newly allocated */
/* HEADER_INFO structure if we allocate one. */
/* */
/* RETURNS: */
/* TRUE Successfully parsed another header from article. */
/* FALSE Failed/no more headers in article. */
/* */
/* COMMENTS: */
/* Adjusts hdr when done so next call will set correct pointer. */
/* BBS version terminates header search on a line without a colon, */
/* or with a space before the colon. Usenet version terminates */
/* header search on blank line, ignoring "malformed" header lines. */
/* */
/* HISTORY: */
/* 1. 02 Sep 89 Created. */
/* 2. 30 Dec 89 Added "Sender:" to list of useful headers. */
/* 3. 21 Oct 90 Don't end header search until blank line. */
/* */
/****************************************************************************/
GetNextHeader( fp, hdr )
FILE *fp;
HEADER_INFO ***hdr;
{
int rc; /* return code from function */
char buf[BUFSIZ]; /* holds input line from article */
char *firstspace, *firstcolon, *data; /* for parsing */
if ( fgets( buf, BUFSIZ, fp ) == NULL )
rc = FALSE;
else
{
firstspace = strchr( buf, ' ' );
firstcolon = strchr( buf, ':' );
if ( ( firstcolon == NULL ) ||
( ( firstspace != NULL ) && ( firstspace < firstcolon ) ) )
{
if ( GetVar( VAR_BBS ) || strspn( buf, " \t\r\n" ) == strlen(buf) )
rc = FALSE;
else /* junk line, don't end header search */
rc = TRUE;
}
else
{
*firstcolon = NULL; /* terminate fieldname string */
# ifndef ARN_CONFIG
/*
* Until a useful way is found to restrict output to interesting headers,
* use this kluge.
*
* Don't actually allocate a header struct because we're not interested in
* other headers, but return TRUE so that we continue to try to get headers.
*/
if ( strcmp( buf, HDR_FROM ) && strcmp( buf, HDR_SUBJECT ) &&
strcmp( buf, HDR_DATE ) && strcmp( buf, HDR_SENDER ) &&
strcmp( buf, HDR_TO ) )
return TRUE;
# endif
firstcolon++; /* advance past colon/NULL to value string */
data = firstcolon + strspn( firstcolon, " \t" ); /* skip white */
data[strlen(data)-1] = NULL; /* remove trailing newline */
/*
* Allocate and fill a new header structure.
*/
**hdr = (HEADER_INFO *) malloc( sizeof( HEADER_INFO ) );
(**hdr)->fieldname = strdup( buf );
(**hdr)->fieldvalue = strdup( data );
(**hdr)->next = NULLP( HEADER_INFO );
/*
* Reset the hdr pointer so next call will continue chain correctly.
*/
*hdr = &((**hdr)->next);
rc = TRUE;
}
}
return rc;
}
/****************************************************************************/
/* FUNCTION: DumpArticle */
/* */
/* PURPOSE: Print article/header info for an article. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* article I Pointer to article structure to dump. */
/* */
/* RETURNS: none */
/* */
/* COMMENTS: */
/* Debugging function. */
/* */
/* HISTORY: */
/* 1. 02 Sep 89 Created. */
/* */
/****************************************************************************/
void DumpArticle( article )
ARTICLE_INFO *article;
{
HEADER_INFO *hdr;
printf( "Article: %ld\n", article->number );
for ( hdr = article->headers; hdr != NULLP( HEADER_INFO ); hdr = hdr->next )
printf( "\t%s: %s\n", hdr->fieldname, hdr->fieldvalue );
printf( "\n" );
}
/****************************************************************************/
/* FUNCTION: DestroyArticle */
/* */
/* PURPOSE: Free all space taken by article/header structure. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* article I The article being destroyed. */
/* */
/* RETURNS: */
/* */
/* COMMENTS: */
/* */
/* HISTORY: */
/* 1. 02 Sep 89 Created. */
/* */
/****************************************************************************/
void DestroyArticle( article )
ARTICLE_INFO *article;
{
HEADER_INFO *hdr, *tmp;
for ( hdr = article->headers; hdr != NULLP( HEADER_INFO ); hdr = tmp )
{
free( hdr->fieldname );
free( hdr->fieldvalue );
tmp = hdr->next;
free( hdr );
}
free( article );
}
/****************************************************************************/
/* FUNCTION: GetHeader */
/* */
/* PURPOSE: Retrieve a specific header from a message. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* headers I List of headers. */
/* name I Name of header to retrieve. */
/* */
/* RETURNS: */
/* */
/* COMMENTS: */
/* Makes a local copy of the header value to be returned. Gets */
/* overwritten each call. */
/* */
/* HISTORY: */
/* 1. 18 Oct 90 Created. */
/* */
/****************************************************************************/
char *GetHeader( headers, name )
HEADER_INFO *headers;
char *name;
{
static char local[MAXLINE];
while ( headers )
{
if ( strcmp( headers -> fieldname, name ) == 0 )
{
strcpy( local, headers -> fieldvalue );
return local;
}
headers = headers -> next;
}
return (char *) NULL;
}